home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-03-09 | 18.6 KB | 504 lines | [TEXT/MPS ] |
- // Copyright © 1993,4 Apple Computer, Inc. All rights reserved
-
- // application constants
- constant kAppSymbol := '|SoupTDS:PIEDTS| ;
- constant kPackageName := "soupTDS:PIEDTS" ;
- constant kAppName := "MetaData";
-
- // soup constants
- constant kAppSoupName := kPackageName ;
- constant kSoupIndices := '[] ;
- constant kAppObject := '["Thing that doesn't suck", "Things that don't suck"];
-
- // metadata constants
- constant kMetaDataVersion := 2 ; // local revision number of our metadata spec
-
- // a date format to use
- DefConst('kAppDateFormat,
- GetDateStringSpec([[kElementHour, kFOrmatNumeric],
- [kElementMinute, kFormatNumeric],
- [kElementAMPM, kFormatAbbr]]));
-
- // ---- End Project Data ----
-
-
- // ---- File Sync Another One.t ----
-
- // Before Script for "MetaDataApp"
- // Copyright © 1993,4 Apple Computer, Inc. All rights reserved
-
- MetaDataApp :=
- {
- viewSetupDoneScript:
- func()
- begin
- tdsSoup := call kRegisterCardSoupFunc with
- (kAppSoupName, kSoupIndices, kAppSymbol, kAppObject);
- // tdsCursor := Query(tdsSoup, {type: 'index, indexPath: 'aString});
- tdsCursor := Query(tdsSoup, {type: 'index});
- if NOT tdsCursor:Entry() then
- :FillSoup();
- :InitMetaData();
- theSoupFrame := tdsCursor:Reset();
- end,
- viewQuitScript:
- func()
- begin
- // unregister card soups
- call kUnregisterCardSoupFunc with (kAppSoupName) ;
-
- // cleanup soup and cursor references
- tdsCursor := nil ;
- tdsSoup := nil ;
-
- // cleanup other extraneous references
- theSoupFrame := nil ;
- theTextFrame := nil ;
- end,
- theTextFrame: nil,
- tdsSoup:
- nil
-
- // holds the soup at runtime,
- TestImport:
- func()
- begin
- if theTextFrame then
- begin
- theSoupFrame := MetaData:import(theTextFrame);
- print(theSoupFrame);
- end else
- :Notify(kNotifyAlert, EnsureInternal(kAppName),
- EnsureInternal("You must first test exporting by pressing the 'Test Export Script' button"));
- end,
- viewBounds: {left: 0, top: 0, right: 240, bottom: 150},
- appObject: kAppObject,
- _proto: protoApp,
- FillSoup:
- func()
- begin
- local i;
- print("Filling Soup");
- for i := 1 to 20 do
- tdsSoup:AddToDefaultStore({
- aString: GetRandomWord(5,20) & $- & GetRandomWord(5,20),
- anInteger: Random(0,10000),
- aReal: Random(0, 10000)/100,
- aSymbol: MySymbolArray[Random(0, length(MySymbolArray)-1)],
- aDate: Time(),
- aTime: Time(),
- aDateAndTime: Time(),
- aCharacter: CHR(Random(ORD($A),ORD($Z))),
- aBoolean: if Random(0, 1) = 1 then TRUE else NIL,
- aFolder: if Random(0, 2) = 0 then nil /* Unfiled */ else
- (foreach folder, name in userConfiguration.userFolders
- collect folder)[
- Random(0, length(userConfiguration.userFolders)-1)],
- aFrame: {
- aStringSlot: GetRandomWord(1,5),
- anIntegerSlot: Random(0, 100),
- },
- anArray: [Random(0, 9), Random(10,19), Random(20,29)],
- });
- if NOT tdsCursor then
- tdsCursor := Query(tdsSoup, {type: 'index});
- theSoupFrame := tdsCursor:Reset();
- end,
- DestroySoup:
- func()
- begin
- local store, myCursor, mySoup, directorySoup;
-
- // unregister soups with system
- call kUnRegisterCardSoupFunc with (kAppSoupName);
-
-
- // remove the soup from each store currently installed
- foreach store in GetStores() do
- if mySoup := store:GetSoup(kAppSoupName) then
- mySoup:RemoveFromStore();
-
- // remove the soup MetaData
- directorySoup := GetStores()[0]:GetSoup("Directory");
- if directorySoup then
- begin
- myCursor := Query(directorySoup, {type:'index, indexPath:'soup,
- startKey: kAppSoupName,
- endTest: func(entry) NOT(StrEqual(entry.soup, kAppSoupName))});
- while myCursor:Entry() do
- begin
- EntryRemoveFromSoup(myCursor:Entry());
- myCursor:Next();
- end;
- end;
-
- // nil out the references to the soup and cursors
- tdsSoup := nil ;
- tdsCursor := nil ;
- theSoupFrame := nil;
- end,
- theSoupFrame: nil,
- appSymbol: kAppSymbol,
- title: "Meta Data Sample",
- MetaData:
- {
- // name of soup within Newton
- soup: kAppSoupName,
-
- // alternate name to show the user
- name: "Meta Data Sample Soup",
-
- // version number, default 1
- version: kMetaDataVersion,
-
- // default frame for a new entry
- newEntry: {
- aString: "default",
- anInteger: 0,
- aReal: 0.0,
- aSymbol: nil,
- aDate: nil, // check out the export script (heh)
- aTime: nil, // check out the export script (heh)
- aDateAndTime: nil, // check out the export script (heh)
- aCharacter: $?,
- aBoolean: NIL,
- aFolder: NIL,
- aFrame: {
- aStringSlot: "default",
- anIntegerSlot: 0,
- },
- anArray: Array(3, 0),
- },
-
- // displayInfo/editInfo/exportInfo entries can have the folowing slots:
- // slot: symbol that refers to slot in soup entry being described
- // type: type of editor for slot, default 'string
- // 'string, 'char, 'text, 'integer, 'picklist, 'folder, 'e_line
- // 'date, 'time, 'real, 'phone (last 4 not fully implemented)
- // choices: in editInfo, array of strings for popups ('picklist)
- // size: number of '0' characters that should fit, default 15
- // hidden: if true, column will initially be hidden
- // label: string for label on Mac/PC, default is slot name
- // sameLine: for editInfo only, if true will put on same line as previous
- // unsearchable: for displayInfo, if true will not allow searches on this field
- // path: specifies path to data for search comparisons, defaults to slot
- // compareScript: symbol for which compare script to use.
- // These are reserved for future use, not implemented now
- // justify: 'right, 'left, 'center, or 'system
- // maxChars: upper limit for input in editInfo
- // minChars: lower limit for input in editInfo
- // maxValue: max for numeric fields in editInfo
- // minValue: min for numeric fields in editInfo
- // validChar: script (in meta data) that will be called for
- // each character in editInfo to validate it.
- // validField: script (in meta data) that will be called when
- // the user finishes the field.
- // numLines: specifies the number of lines for editInfo
-
- // used in overview list on Mac/PC, order in array controls Mac/PC
- displayInfo: ['aString, 'anInteger, 'aReal, 'aSymbol, 'aDate, 'aTime,
- 'aDateAndTime, 'aCharacter, 'aBoolean, 'aFolder,],
- // 'aFrame1, 'aFrame2, 'anArray1, 'anArray2, 'anArray3],
-
- // used in item list on Mac/PC
- editInfo: ['aString, 'anInteger, 'aReal, 'aSymbol, 'e_line, 'aDate, 'aTime,
- 'aDateAndTime, 'e_line, 'aCharacter, 'aBoolean, 'aFolder, 'e_line,
- 'aFrame1, 'aFrame2, 'anArray1, 'anArray2, 'anArray3],
-
- // used for import/export on Mac/PC
- exportInfo: ['aString, 'anInteger, 'aReal, 'aSymbol, 'aDate, 'aTime,
- 'aDateAndTime, 'aCharacter, 'aBoolean, 'aFolder,
- 'aFrame1, 'aFrame2, 'anArray1, 'anArray2, 'anArray3],
-
- // specifies defaults in displayInfo, editInfo, exportInfo
- defaultDefinitions: {
- aString: {slot: 'aString, size: 41, },
- anInteger: {slot: 'anInteger, type: 'integer, },
- aReal: {slot: 'aReal, type: 'real, },
- aSymbol: {slot: 'aSymbol, type: 'mySymbolType, size: 12, },
- aDate: {slot: 'aDate, type: 'date, },
- aTime: {slot: 'aTime, type: 'time, sameline: TRUE, },
- aDateAndTime: {slot: 'aDateAndTime, type: 'myDateAndTime, },
- aCharacter: {slot: 'aCharacter, type: 'char, },
- aBoolean: {slot: 'aBoolean, type: 'picklist, label: "Boolean", choices: ["TRUE", "FALSE"], },
- aFolder: {slot: 'aFolder, type: 'folder, },
- aFrame1: {slot: 'aFrame.aStringSlot, hidden: TRUE, size: 11, },
- aFrame2: {slot: 'aFrame.anIntegerSlot, type: 'integer, hidden: TRUE, },
- anArray1: {slot: [pathExpr: 'anArray, 0], type: 'integer, hidden: TRUE, },
- anArray2: {slot: [pathExpr: 'anArray, 1], type: 'integer, hidden: TRUE, },
- anArray3: {slot: [pathExpr: 'anArray, 2], type: 'integer, hidden: TRUE, },
- },
-
- // used to lookup values of type slots
- // must be one of:
- // 'string, 'char, 'text, 'integer, 'picklist, 'folder, 'e_line
- // 'date, 'time, 'real, 'phone (last 4 not fully implemented)
- editTypes: {
- mySymbolType: {type: 'picklist, label: "Symbol", choices: ["first", "second", "third", ], },
- },
-
- // text frames have same slots as soup frames, but value
- // for each slot is a string. The textFrame should also have a slot called
- // originalFrame, which should point to the soup frame (just a convention)
- // Note that the text frame passed to the import script will NOT be the same
- // frame returned from the export script. (Any slots not mentioned in editInfo
- // won't appear in the frame passed to the import script.)
-
- export: func(theSoupFrame)
- begin
- local theTextFrame := {
- // originalFrame: theSoupFrame,
- aString: theSoupFrame.aString,
- anInteger: SPrintObject(theSoupFrame.anInteger),
- aReal: SPrintObject(theSoupFrame.aReal),
- aSymbol: :MySymbolToString(theSoupFrame.aSymbol),
- aDate: ShortDateStr(if NOT theSoupFrame.aDate then Time() else theSoupFrame.aDate, kIncludeAllElements),
- aTime: TimeStr(if NOT theSoupFrame.aTime then Time() else theSoupFrame.aTime,kAppDateFormat),
- aDateAndTime: ShortDateStr(if NOT theSoupFrame.aDate then Time() else theSoupFrame.aDate, kIncludeAllElements)
- && TimeStr(if NOT theSoupFrame.aTime then Time() else theSoupFrame.aTime, kAppDateFormat),
- aCharacter: SPrintObject(theSoupFrame.aCharacter),
- aBoolean: defaultDefinitions.aBoolean.choices[if theSoupFrame.aBoolean then 0 else 1],
- aFolder: if theSoupFrame.aFolder then SPrintObject(theSoupFrame.aFolder),
- aFrame1: theSoupFrame.aFrame.aStringSlot,
- aFrame2: SPrintObject(theSoupFrame.aFrame.anIntegerSlot),
- anArray1: SPrintObject(theSoupFrame.anArray[0]),
- anArray2: SPrintObject(theSoupFrame.anArray[1]),
- anArray3: SPrintObject(theSoupFrame.anArray[2]),
- };
- return theTextFrame
- end,
-
- // convert a text frame to a soup entry frame
- import: func(theTextFrame)
- begin
- local n := StringToNumber(theTextFrame.anInteger);
- local m := StringToNumber(theTextFrame.aFrame2);
- local o := [
- StringToNumber(theTextFrame.anArray1),
- StringToNumber(theTextFrame.anArray2),
- StringToNumber(theTextFrame.anArray3),
- ];
- local theSoupFrame := {
- aString: theTextFrame.aString,
- anInteger: if n = abs(n) then floor(n) else ceiling(n),
- aReal: StringToNumber(theTextFrame.aReal),
- aSymbol: :StringToMySymbol(theTextFrame.aSymbol),
- aDate: StringToDate(theTextFrame.aDate),
- aTime: :GetTime(theTextFrame.atime),
- aDateAndTime: StringToDate(theTextFrame.aDateAndTime),
- aCharacter: if length(theTextFrame.aCharacter) > 0 then theTextFrame.aCharacter[0] else $ ,
- aBoolean: StrCompare(theTextFrame.aBoolean, defaultDefinitions.aBoolean.choices[0]) = 0,
- aFolder: if theTextFrame.aFolder then :GetSymbol(theTextFrame.aFolder),
- aFrame: {
- aStringSlot: theTextFrame.aFrame1,
- anIntegerSlot: if m = abs(m) then floor(m) else ceiling(m),
- },
- anArray: [
- if o[0] = abs(o[0]) then floor(o[0]) else ceiling(o[0]),
- if o[1] = abs(o[1]) then floor(o[1]) else ceiling(o[1]),
- if o[2] = abs(o[2]) then floor(o[2]) else ceiling(o[2]),
- ],
- };
- return theSoupFrame;
- end,
-
- // these supporting functions are used by import/export to
- // convert strings to symbols and vice-versa. They're accessible
- // because the context for the import and export scripts is a copy
- // of the meta data frame itself.
- MySymbolToString: func(theSymbol)
- editTypes.mySymbolType.choices[
- if NOT theSymbol or theSymbol = 'firstSymbol then 0
- else if theSymbol = 'secondSymbol then 1
- else if theSymbol = 'thirdSymbol then 2
- ],
-
- StringToMySymbol: func(theString)
- if StrCompare(theString, editTypes.mySymbolType.choices[0]) = 0 then 'firstSymbol
- else if StrCompare(theString, editTypes.mySymbolType.choices[1]) = 0 then 'secondSymbol
- else if StrCompare(theString, editTypes.mySymbolType.choices[2]) = 0 then 'thirdSymbol
- else 'firstSymbol,
-
- // need to put a wrapper around the functions that could make a symbol
- // 1.0 uses MakeSymbol, 2.0 uses Intern
- GetSymbol: func(string)
- if functions.Intern then
- Intern(string)
- else
- MakeSymbol(String),
-
- // yet another function to account for differences between 1.0 and 2.0
- // in 1.0, StringToTime is broken, so you have to use StringToDate,
- // but this will add todays date to the time.
- GetTime: func(string)
- if ClassOf(StringToTime("11:00 am")) = 'frame then
- StringToDate(string)
- else
- StringToTime(string),
-
-
- // used to write custom comparisons for fields.
- // Slots are references by compareScript slots in displayInfo array.
- // description contains:
- // slotname: path to data within the current frame
- // datatype: value of 'type slot in frame
- // searchtype: search requested by user (0-9)
- // searchtext: what the user typed in
- // searchvalue: use to store converted values from searchtext
- RealCompare: func(entry, description)
- begin
- TRUE;
- end,
-
- compareScripts: {
- aRealCompare: func (entry, description) :RealCompare(entry, description),
- aSymbolCompare: func (entry, description) TRUE,
- },
- },
- tdsCursor: nil,
- TestExport:
- func()
- begin
- if theSoupFrame then
- begin
- theTextFrame := MetaData:export(theSoupFrame);
- print(theTextFrame);
- end else
- :Notify(kNotifyAlert, EnsureInternal(kAppName),
- EnsureInternal("There is no soup, create one by pressing the 'Rebuild the Soup!' button"));
- end,
- MySymbolArray:
- [
- 'firstSymbol,
- 'secondSymbol,
- 'thirdSymbol,
- ],
- TestNewEntry:
- func()
- begin
- if tdsSoup then
- begin
- theSoupFrame := DeepClone(MetaData.newEntry);
- tdsSoup:Add(theSoupFrame);
- theTextFrame := MetaData:export(theSoupFrame);
- print(theTextFrame);
- end else
- :Notify(kNotifyAlert, EnsureInternal(kAppName),
- EnsureInternal("There is no soup to add to. Rebuild using the 'Rebuild the Soup!' button"));
- end,
- debug: "MetaDataApp",
- InitMetaData:
- func()
- begin
- // remove any old soup MetaData then add the latest
- local addEntry := nil ;
- local directorySoup := GetStores()[0]:GetSoup("Directory");
- if directorySoup then
- begin
- // get a the metaData soup entry
- myCursor := Query(directorySoup, {type:'index, indexPath:'soup,
- startKey: kAppSoupName,
- endTest: func(entry) NOT(StrEqual(entry.soup, kAppSoupName))});
-
- // if the metaData spec is not the latest version
- // for the app, remove it
- if myCursor:Entry() AND (myCursor:Entry().version < kMetaDataVersion) then
- begin
- EntryRemoveFromSoup(myCursor:Entry());
- addEntry := true ;
- // if this happens, could be other stuff to remove
- while myCursor:Next() do
- EntryRemoveFromSoup(myCursor:Entry());
- end;
-
- // if needed, add a metaData entry
- if addEntry then
- directorySoup:Add(Clone(MetaData));
- end;
- end
- };
-
- testExportButton := /* child of MetaDataApp */
- {text: "Test Export Script",
- buttonClickScript:
- func()
- begin
- :Parent():TestExport();
- end,
- viewBounds: {left: 28, top: 20, right: 212, bottom: 36},
- _proto: protoTextButton,
- debug: "testExportButton"
- };
-
-
-
- testImportButton := /* child of MetaDataApp */
- {text: "Test Import Script",
- buttonClickScript:
- func()
- begin
- :Parent():TestImport();
- end,
- viewBounds: {left: 28, top: 44, right: 212, bottom: 60},
- _proto: protoTextButton,
- debug: "testImportButton"
- };
-
-
-
- testNewButton := /* child of MetaDataApp */
- {text: "Test New Entry",
- buttonClickScript:
- func()
- begin
- :Parent():TestNewEntry();
- end,
- viewBounds: {left: 28, top: 68, right: 212, bottom: 84},
- _proto: protoTextButton,
- debug: "testNewButton"
- };
-
-
-
- rebuildSoup := /* child of MetaDataApp */
- {text: "Rebuild the Soup!",
- buttonClickScript:
- func()
- begin
- foreach store in GetStores() do begin
- if soup := store:GetSoup(kAppSoupName) then
- soup:RemoveAllEntries();
- end;
- if not tdsSoup then
- tdsSoup := call kRegisterCardSoupFunc with
- (kAppSoupName, kSoupIndices, kAppSymbol, kAppObject);
- :FillSoup();
- end,
- viewBounds: {left: 28, top: 92, right: 210, bottom: 106},
- _proto: protoTextButton,
- debug: "rebuildSoup"
- };
-
-
-
- zapSoup := /* child of MetaDataApp */
- {text: "Delete the Soup!",
- buttonClickScript:
- func()
- begin
- :DestroySoup();
- end,
- viewBounds: {left: 28, top: 116, right: 210, bottom: 130},
- _proto: protoTextButton,
- debug: "zapSoup"
- };
-
-
-
-
-
-
-
- // ---- Beginning of section for non used Layout files ----
-
- // End of output